﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web.SessionState;
using System.Web;
using System.Collections.Specialized;
using System.Diagnostics;
using SaturniLibrary.Web;

namespace SaturniLibrary.Web.Log
{
    internal class WebLogHelper
    {
        internal static string CreateExceptionLogPath()
        {
            DateTime now = DateTime.Now;
            return "" + Path.DirectorySeparatorChar + now.Year
                   + Path.DirectorySeparatorChar + now.Month
                   + Path.DirectorySeparatorChar + now.Day
                   + Path.DirectorySeparatorChar + Guid.NewGuid()
                   + ".log";
        }

        internal static void CreateLogFile(string exceptionLogPath)
        {
            if (!File.Exists(exceptionLogPath))
            {
                FileInfo fileInfo = new FileInfo(exceptionLogPath);
                if (fileInfo.Directory != null)
                {
                    fileInfo.Directory.Create();
                }
            }

            File.AppendAllText(exceptionLogPath, ThreadLogging.GetLogger().GetAllLogs());
            File.AppendAllText(exceptionLogPath, ThreadLogging.GetLogger().GetAllTransactions());
        }

        internal static void LogSession(HttpSessionState session)
        {
            if (session != null)
            {
                ThreadLogging.GetLogger().Log("Session Data");
                foreach (string key in session.Keys)
                {
                    ThreadLogging.GetLogger().Log("Name=" + key + ", Value=" + session[key]);
                }
            }
        }

        internal static void LogRequestInfo(HttpRequest request)
        {
            if (request != null)
            {
                ThreadLogging.GetLogger().Log("Http Request data");

                try
                {
                    HttpCookieCollection cookies = request.Cookies;
                    foreach (HttpCookie cookie in cookies)
                    {
                        ThreadLogging.GetLogger().Log("Http Cookie, name=" + cookie.Name + ", value=" + cookie.Value);
                    }
                }
                catch
                {
                }

                try
                {
                    NameValueCollection queryParams = request.QueryString;
                    foreach (string param in queryParams)
                    {
                        ThreadLogging.GetLogger().Log("Http Param, name=" + param + ", value=" + queryParams[param]);
                    }
                }
                catch
                {
                }

                try
                {
                    NameValueCollection formParams = request.Form;
                    foreach (string formParam in formParams)
                    {
                        ThreadLogging.GetLogger().Log("Http Form, name=" + formParam + ", value=" + formParams[formParam]);
                    }
                }
                catch
                {
                }
            }
        }

        internal static string FindHeader(HttpRequest request, string headerName)
        {
            try
            {
                return request.Headers.Get(headerName);
            }
            catch
            {
                return string.Empty;
            }
        }

        internal static string GetContextPage(HttpRequest request)
        {
            int index = request.Path.LastIndexOf("/");
            if (index >= 0)
            {
                return request.Path.Substring(index + 1);
            }
            else
            {
                return request.Path;
            }
        }

        internal static void SaveExceptionLog(Exception exception, HttpContext context)
        {
            try
            {
                OutputException(exception);

                Exception innerException = exception;
                if (innerException != null)
                {
                    while (innerException.InnerException != null)
                    {
                        innerException = innerException.InnerException;
                        OutputException(innerException);
                    }
                }

                WebLogDetail exceptionLog = new WebLogDetail();
                exceptionLog.HostName = Environment.MachineName;
                exceptionLog.ModuleName = string.IsNullOrEmpty(context.Request.ServerVariables["HTTP_HOST"]) ? "Unknown" : context.Request.ServerVariables["HTTP_HOST"];
                exceptionLog.ExceptionSource = WebLogHelper.GetContextPage(context.Request);
                exceptionLog.ExceptionType = exception == null ? "None" : exception.GetType().FullName;
                exceptionLog.ExceptionLogPath = WebLogHelper.CreateExceptionLogPath();
                exceptionLog.ClientIp = context.Request.GetRemoteIp();
                exceptionLog.UserAgent = WebLogHelper.FindHeader(context.Request, "User-Agent");
                exceptionLog.Ticket = ThreadLogging.GetLogger().Ticket;
                exceptionLog.ExecutionTime = ThreadLogging.GetLogger().GetStopWatch().ElapsedMs();
                WebLogHelper.CreateLogFile(WebLogConfig.Instance.LogFolder + exceptionLog.ExceptionLogPath);
                WebLogConfig.Instance.DataProvider.Insert(exceptionLog);
            }
            catch
            {
            }
        }

        internal static void OutputException(Exception exception)
        {
            if (exception != null)
            {
                ThreadLogging.GetLogger().Log("Exception Type=" + exception.GetType().FullName);
                ThreadLogging.GetLogger().Log("Exception Message=" + exception.Message);
                ThreadLogging.GetLogger().Log("Exception Thrown=" + exception.TargetSite);
                ThreadLogging.GetLogger().Log("Exception Trace=" + new StackTrace(exception, true));
                ThreadLogging.GetLogger().Log("Exception Source=" + exception.Source);
            }
        }
    }
}
